package com.jboost.modules.system.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jboost.common.constant.CommonConstant;
import com.jboost.common.constant.DataBaseConstant;
import com.jboost.common.system.vo.LoginUser;
import com.jboost.common.util.oConvertUtils;
import com.jboost.config.mybatis.TenantContext;
import com.jboost.modules.system.entity.*;
import com.jboost.modules.system.service.*;
import lombok.extern.slf4j.Slf4j;
import com.jboost.modules.system.mapper.SysTenantMapper;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.FileCopyUtils;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class SysTenantServiceImpl extends ServiceImpl<SysTenantMapper, SysTenant> implements ISysTenantService {

    @Autowired
    ISysPermissionService sysPermissionService;

    @Autowired
    ISysUserService sysUserService;

    @Autowired
    ISysRoleService sysRoleService;

    @Autowired
    ISysUserRoleService sysUserRoleService;

    @Autowired
    ISysRolePermissionService sysRolePermissionService;
    @Autowired
    ISysPermissionDataRuleService sysPermissionDataRuleService;

    private List<SysPermission> getPermissionList(){
        //  如果设置了BaseFlag字段配置 可以读取数据库
/*      LambdaQueryWrapper<SysPermission> query = new LambdaQueryWrapper<SysPermission>();
        query.eq(SysPermission::getBaseFlag, true);
        query.eq(SysPermission::getTenantId, 1);
        List<SysPermission> ls = sysPermissionService.list(query);*/
        // 读取json  需要自己提前在baseRoute.json文件里配置菜单信息
        String jsonPath = "static/system/baseRoute.json";
        ClassPathResource classPathResource = new ClassPathResource(jsonPath);
        byte[] bytes = new byte[0];
        try {
            bytes = FileCopyUtils.copyToByteArray(classPathResource.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
        String json = new String(bytes);
        JSONArray array = JSON.parseArray(json);
        List<SysPermission> ls = array.toJavaList(SysPermission.class);
        return ls;
    }

    @Override
    @Transactional
    public void saveStoreTenant(SysTenant sysTenant) {
        this.save(sysTenant);
        String storeId = sysTenant.getBusinessId();
        List<SysPermission> ls = getPermissionList();
        Collection<String> menuIds = setPermissionTenant(ls, storeId);
        //后面的操作就要切换成正式的租户了
        TenantContext.setTenant(storeId);
        sysPermissionService.saveBatch(ls);

        // 修改当前用户的租户
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        SysUser user = sysUserService.getById(sysUser.getId());
        String refTenantIds = user.getRelTenantIds();
        if(oConvertUtils.isEmpty(refTenantIds)){
            user.setRelTenantIds(storeId);
        }else{
            user.setRelTenantIds(refTenantIds+","+storeId);
        }
        sysUserService.updateById(user);

        // 添加『店铺管理员』角色
        SysRole role = new SysRole();
        role.setRoleCode(sysTenant.getPreCode()+"_admin");
        role.setRoleName("店铺管理员");
//        role.setStoreId(storeId);
        TenantContext.setTenant(storeId);
        //会主动设置成租户 id
        sysRoleService.save(role);


        // 添加角色 用户关系
        SysUserRole sysUserRole = new SysUserRole();
        // TODO is ok？
        sysUserRole.setRoleId(role.getId());
        sysUserRole.setUserId(user.getId());
        sysUserRoleService.save(sysUserRole);

        //用户列表-的数据权限
        SysPermissionDataRule userListRule = addPermissionDataRule(ls);

        // 添加角色 菜单关系
        List<SysRolePermission> list = new ArrayList<>();
        for(String menuId: menuIds){
            SysRolePermission sp = new SysRolePermission();
            sp.setPermissionId(menuId);
            sp.setRoleId(role.getId());
            //用户管理需要加数据权限
            if (null!=userListRule && userListRule.getPermissionId().equals(menuId)){
                sp.setDataRuleIds(userListRule.getId());
            }
            list.add(sp);
        }
        sysRolePermissionService.saveBatch(list);
    }


    private String randomId(){
        long id = IdWorker.getId();
        return String.valueOf(id);
    }

    private Collection<String> setPermissionTenant(List<SysPermission> ls, String storeId){
        // 循环两次 第一次设置ID和tenantId 第二次设置pid
        Map<String, String> map = new HashMap<>();
        for(SysPermission p: ls){
            String oldId = p.getId();
            String newId = randomId();
            map.put(oldId, newId);
            p.setId(newId);
//            p.setStoreId(null);//设置为 null，insert 语句就不会有了，通过租户拦截补充租户id
            p.setCreateBy(null);
            p.setCreateTime(null);
            p.setUpdateBy(null);
            p.setUpdateTime(null);
        }
        for(SysPermission p: ls){
            String oldPid = p.getParentId();
            if(oConvertUtils.isNotEmpty(oldPid)){
                String newPid = map.get(oldPid);
                if(oConvertUtils.isNotEmpty(newPid)){
                    p.setParentId(newPid);
                }else{
                    // TODO 一般情况下这个newPid是肯定有值的  如果没有值 说明当前节点的父节点 没有设置为基础路由  那么 需要递归获取 所有父级节点 挨个设置一下即可
                }
            }
        }
        return map.values();
    }

    @Override
    public void createPermission(SysUser user,boolean isClear) {

        String storeId = null;
        if(isClear){
            sysPermissionService.remove(new LambdaQueryWrapper<SysPermission>());
            SysRole role = sysRoleService.lambdaQuery().eq(SysRole::getBusinessId,storeId).eq(SysRole::getRoleCode,storeId+"_admin").one();
            String roleId = role.getId();
            if(null != role){
                sysRoleService.removeById(roleId);
            }
            sysRolePermissionService.remove(new LambdaQueryWrapper<SysRolePermission>().eq(SysRolePermission::getRoleId,roleId));
        }
        //找出 base菜单
        LambdaQueryWrapper<SysPermission> query = new LambdaQueryWrapper<SysPermission>();
//        query.eq(SysPermission::getBaseFlag, 1);
//        query.eq(SysPermission::getStoreId, 1);
        List<SysPermission> ls = sysPermissionService.list(query);
        Collection<String> menuIds = setPermissionTenant(ls, storeId);
        TenantContext.setTenant(storeId);
        sysPermissionService.saveBatch(ls);

        //用户列表-的数据权限
        SysPermissionDataRule userListRule = addPermissionDataRule(ls);

        // 添加角色 菜单关系
        //『店铺管理员』角色
        SysRole role = sysRoleService.lambdaQuery().eq(SysRole::getBusinessId,storeId).eq(SysRole::getRoleCode,storeId+"_admin").one();
        if(null == role){
            // 添加『店铺管理员』角色
            role = new SysRole();
            role.setRoleCode(storeId+"_admin");
            role.setRoleName("店铺管理员");
//        role.setStoreId(storeId);
            sysRoleService.save(role);
        }
        List<SysRolePermission> list = new ArrayList<>();
        for(String menuId: menuIds){
            SysRolePermission sp = new SysRolePermission();
            sp.setPermissionId(menuId);
            sp.setRoleId(role.getId());
            //用户管理需要加数据权限
            if (null!=userListRule && userListRule.getPermissionId().equals(menuId)){
                sp.setDataRuleIds(userListRule.getId());
            }
            list.add(sp);
        }
        sysRolePermissionService.saveBatch(list);
    }

    private SysPermissionDataRule addPermissionDataRule(List<SysPermission> ls) {

        SysPermission userListPermission = ls.stream().filter(sp->CommonConstant.SYS_USER_PERMISSION_COMPONENT.equals(sp.getComponent())).findFirst().orElse(null);
        if (null!=userListPermission){
            SysPermissionDataRule dataRule = new SysPermissionDataRule();
            dataRule.setPermissionId(userListPermission.getId());
            dataRule.setStatus(CommonConstant.STATUS_1);
            dataRule.setRuleName("只能查看自己店铺的");
            dataRule.setRuleColumn(DataBaseConstant.STORE_ID);
            dataRule.setRuleConditions("=");
            dataRule.setRuleValue(DataBaseConstant.STORE_ID_TABLE);
            sysPermissionDataRuleService.save(dataRule);
            return dataRule;
        }
        return null;
    }
}
